#include "QOverlay.h"
#include <QResizeEvent>
#include <QApplication>
#include <algorithm>
#include <cassert>

// ==================== OverlaySlot Implementation ====================

QOverlay::OverlaySlot::OverlaySlot(QWidget* widget, qreal zValue)
    : Widget(widget)
    , ProxyWidget(nullptr)
    , ZValue(zValue)
    , Alignment(OverlayAlignment::TopLeft)
    , Padding(0, 0, 0, 0)
    , SizeHintValue(-1, -1)
{
    // 断言：控件不应该为空
    assert(widget != nullptr && "Widget cannot be null in OverlaySlot");
    
    if (Widget)
    {
        ProxyWidget = new QGraphicsProxyWidget();
        ProxyWidget->setWidget(Widget);
        ProxyWidget->setZValue(ZValue);
    }
}

QOverlay::OverlaySlot::~OverlaySlot()
{
    // 不删除widget，由QOverlay管理
}

void QOverlay::OverlaySlot::setWidget(QWidget* widget)
{
    if (Widget != widget)
    {
        Widget = widget;
    }
}

void QOverlay::OverlaySlot::setZValue(qreal zValue)
{
    if (ZValue != zValue)
    {
        ZValue = zValue;
        if (ProxyWidget)
        {
            ProxyWidget->setZValue(zValue);
        }
    }
}

void QOverlay::OverlaySlot::setAlignment(OverlayAlignment alignment) {
    if (Alignment != alignment) {
        Alignment = alignment;
    }
}

void QOverlay::OverlaySlot::setPadding(const QMargins& padding) {
    if (Padding != padding) {
        Padding = padding;
    }
}

void QOverlay::OverlaySlot::setPadding(int left, int top, int right, int bottom) {
    setPadding(QMargins(left, top, right, bottom));
}

void QOverlay::OverlaySlot::setSizeHint(const QSize& size) {
    SizeHintValue = size;
}

bool QOverlay::OverlaySlot::isVisible() const {
    return ProxyWidget ? ProxyWidget->isVisible() : false;
}

void QOverlay::OverlaySlot::setVisible(bool visible) {
    if (ProxyWidget) {
        ProxyWidget->setVisible(visible);
    }
}

qreal QOverlay::OverlaySlot::opacity() const {
    return ProxyWidget ? ProxyWidget->opacity() : 1.0;
}

void QOverlay::OverlaySlot::setOpacity(qreal opacity) {
    if (ProxyWidget) {
        ProxyWidget->setOpacity(qBound(0.0, opacity, 1.0));
    }
}

// ==================== QOverlay Implementation ====================

QOverlay::QOverlay(QWidget* parent)
    : QGraphicsView(parent)
    , Scene(nullptr)
    , NeedsArrange(false)
{
    // 创建场景
    Scene = new QGraphicsScene(this);
    setScene(Scene);
    
    // 设置视图属性
    setFrameStyle(QFrame::NoFrame);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setRenderHint(QPainter::Antialiasing, true);
    
    // 设置场景矩形为视图大小
    setSceneRect(0, 0, width(), height());
}

QOverlay::~QOverlay() {
    clearSlots();
}

QOverlay::OverlaySlot* QOverlay::addWidget(QWidget* widget, qreal zValue, 
                                          OverlayAlignment alignment) {
    return addWidget(widget, zValue, alignment, QMargins());
}

QOverlay::OverlaySlot* QOverlay::addWidget(QWidget* widget, qreal zValue, 
                                          OverlayAlignment alignment, 
                                          const QMargins& padding) {
    if (!widget) return nullptr;
    
    // 如果zValue为-1，自动分配
    if (zValue == -1) {
        zValue = Slots.isEmpty() ? 0 : (Slots.last()->zValue() + 1);
    }
    
    auto slot = new OverlaySlot(widget, zValue);
    slot->setAlignment(alignment);
    slot->setPadding(padding);
    
    // 添加到场景
    if (slot->proxyWidget()) {
        Scene->addItem(slot->proxyWidget());
    }
    
    // 按Z顺序插入
    insertSlotByZValue(slot);
    
    // 更新布局
    NeedsArrange = true;
    arrangeSlots();
    
    emit slotAdded(slot);
    return slot;
}

void QOverlay::removeWidget(QWidget* widget) {
    for (auto it = Slots.begin(); it != Slots.end(); ++it) {
        if ((*it)->widget() == widget) {
            auto slot = *it;
            Slots.erase(it);
            
            // 从场景中移除
            if (slot->proxyWidget()) {
                Scene->removeItem(slot->proxyWidget());
            }
            delete slot;
            
            NeedsArrange = true;
            arrangeSlots();
            
            emit slotRemoved(slot);
            break;
        }
    }
}

void QOverlay::removeSlot(OverlaySlot* slot) {
    if (!slot) return;
    
    auto it = std::find(Slots.begin(), Slots.end(), slot);
    if (it != Slots.end()) {
        Slots.erase(it);
        
        if (slot->widget()) {
            slot->widget()->setParent(nullptr);
        }
        delete slot;
        
        NeedsArrange = true;
        arrangeSlots();
        
        emit slotRemoved(slot);
    }
}

void QOverlay::clearSlots() {
    for (auto slot : Slots) {
        if (slot->widget()) {
            slot->widget()->setParent(nullptr);
        }
        delete slot;
    }
    Slots.clear();
    NeedsArrange = true;
}

bool QOverlay::hasSlotWithZValue(qreal zValue) const {
    return getSlotByZValue(zValue) != nullptr;
}

QOverlay::OverlaySlot* QOverlay::getSlotByZValue(qreal zValue) const {
    for (auto slot : Slots) {
        if (slot->zValue() == zValue) {
            return slot;
        }
    }
    return nullptr;
}

void QOverlay::moveSlotToFront(OverlaySlot* slot) {
    if (!slot || Slots.isEmpty()) return;
    
    qreal maxZValue = Slots.last()->zValue();
    slot->setZValue(maxZValue + 1);
    sortSlotsByZValue();
    
    NeedsArrange = true;
    arrangeSlots();
    
    emit zOrderChanged(slot);
}

void QOverlay::moveSlotToBack(OverlaySlot* slot) {
    if (!slot || Slots.isEmpty()) return;
    
    qreal minZValue = Slots.first()->zValue();
    slot->setZValue(minZValue - 1);
    sortSlotsByZValue();
    
    NeedsArrange = true;
    arrangeSlots();
    
    emit zOrderChanged(slot);
}

QOverlay::OverlaySlot* QOverlay::slotAt(int index) const {
    if (index >= 0 && index < Slots.size()) {
        return Slots[index];
    }
    return nullptr;
}

QOverlay::OverlaySlot* QOverlay::addCenteredWidget(QWidget* widget, qreal zValue) {
    return addWidget(widget, zValue, OverlayAlignment::Center);
}

QOverlay::OverlaySlot* QOverlay::addTopRightWidget(QWidget* widget, qreal zValue, 
                                                  const QMargins& padding) {
    return addWidget(widget, zValue, OverlayAlignment::TopRight, padding);
}

QOverlay::OverlaySlot* QOverlay::addBottomLeftWidget(QWidget* widget, qreal zValue, 
                                                    const QMargins& padding) {
    return addWidget(widget, zValue, OverlayAlignment::BottomLeft, padding);
}

void QOverlay::resizeEvent(QResizeEvent* event) {
    QGraphicsView::resizeEvent(event);
    
    // 更新场景矩形
    setSceneRect(0, 0, event->size().width(), event->size().height());
    
    NeedsArrange = true;
    arrangeSlots();
}

void QOverlay::childEvent(QChildEvent* event) {
    QWidget::childEvent(event);
    
    if (event->type() == QEvent::ChildAdded || 
        event->type() == QEvent::ChildRemoved) {
        NeedsArrange = true;
        QApplication::postEvent(this, new QEvent(QEvent::LayoutRequest));
    }
}

QSize QOverlay::sizeHint() const {
    QSize maxSize(0, 0);
    
    for (auto slot : Slots) {
        if (slot->widget() && slot->isVisible()) {
            QSize childSize = slot->widget()->sizeHint() + 
                             QSize(slot->padding().left() + slot->padding().right(),
                                   slot->padding().top() + slot->padding().bottom());
            maxSize = maxSize.expandedTo(childSize);
        }
    }
    
    return maxSize.isEmpty() ? QSize(100, 100) : maxSize;
}

QSize QOverlay::minimumSizeHint() const {
    QSize maxSize(0, 0);
    
    for (auto slot : Slots) {
        if (slot->widget() && slot->isVisible()) {
            QSize childSize = slot->widget()->minimumSizeHint() + 
                             QSize(slot->padding().left() + slot->padding().right(),
                                   slot->padding().top() + slot->padding().bottom());
            maxSize = maxSize.expandedTo(childSize);
        }
    }
    
    return maxSize.isEmpty() ? QSize(50, 50) : maxSize;
}

void QOverlay::arrangeSlots() {
    if (!NeedsArrange) return;
    
    const QRectF availableRect = sceneRect();
    
    for (auto slot : Slots) {
        if (slot->proxyWidget() && slot->isVisible()) {
            updateSlotGeometry(slot);
        }
    }
    
    NeedsArrange = false;
}

void QOverlay::updateSlotGeometry(OverlaySlot* slot) {
    if (!slot || !slot->proxyWidget()) return;
    
    const QRectF availableRect = sceneRect();
    const QRectF slotGeometry = calculateSlotGeometry(slot, availableRect);
    
    slot->proxyWidget()->setGeometry(slotGeometry);
    slot->proxyWidget()->setVisible(slot->isVisible());
}

QRectF QOverlay::calculateSlotGeometry(OverlaySlot* slot, const QRectF& availableRect) const {
    if (!slot || !slot->widget()) return QRectF();
    
    const QMargins padding = slot->padding();
    const QRectF contentRect = availableRect.marginsRemoved(padding);
    
    QSize widgetSize = slot->sizeHint().isValid() ? 
                       slot->sizeHint() : 
                       slot->widget()->sizeHint();
    
    // 如果没有有效的sizeHint，使用widget的首选大小
    if (!widgetSize.isValid()) {
        widgetSize = slot->widget()->sizeHint();
    }
    
    QRectF result;
    
    switch (slot->alignment()) {
        case OverlayAlignment::TopLeft:
            result = QRectF(contentRect.topLeft(), widgetSize);
            break;
            
        case OverlayAlignment::TopCenter:
            result = QRectF(QPointF(contentRect.center().x() - widgetSize.width() / 2, 
                                   contentRect.top()), widgetSize);
            break;
            
        case OverlayAlignment::TopRight:
            result = QRectF(QPointF(contentRect.right() - widgetSize.width(), 
                                   contentRect.top()), widgetSize);
            break;
            
        case OverlayAlignment::CenterLeft:
            result = QRect(QPoint(contentRect.left(), 
                                  contentRect.center().y() - widgetSize.height() / 2), 
                          widgetSize);
            break;
            
        case OverlayAlignment::Center:
            result = QRect(QPoint(contentRect.center().x() - widgetSize.width() / 2,
                                  contentRect.center().y() - widgetSize.height() / 2), 
                          widgetSize);
            break;
            
        case OverlayAlignment::CenterRight:
            result = QRect(QPoint(contentRect.right() - widgetSize.width(),
                                  contentRect.center().y() - widgetSize.height() / 2), 
                          widgetSize);
            break;
            
        case OverlayAlignment::BottomLeft:
            result = QRect(QPoint(contentRect.left(),
                                  contentRect.bottom() - widgetSize.height()), 
                          widgetSize);
            break;
            
        case OverlayAlignment::BottomCenter:
            result = QRect(QPoint(contentRect.center().x() - widgetSize.width() / 2,
                                  contentRect.bottom() - widgetSize.height()), 
                          widgetSize);
            break;
            
        case OverlayAlignment::BottomRight:
            result = QRect(QPoint(contentRect.right() - widgetSize.width(),
                                  contentRect.bottom() - widgetSize.height()), 
                          widgetSize);
            break;
            
        case OverlayAlignment::Fill:
            result = contentRect;
            break;
    }
    
    // 确保不超出可用区域
    result = result.intersected(availableRect);
    
    return result;
}

void QOverlay::insertSlotByZValue(OverlaySlot* slot) {
    if (!slot) return;
    
    // 找到正确的插入位置
    auto it = std::lower_bound(Slots.begin(), Slots.end(), slot,
                              [](const OverlaySlot* a, const OverlaySlot* b) {
                                  return a->zValue() < b->zValue();
                              });
    
    Slots.insert(it, slot);
}

void QOverlay::sortSlotsByZValue() {
    std::sort(Slots.begin(), Slots.end(),
              [](const OverlaySlot* a, const OverlaySlot* b) {
                  return a->zValue() < b->zValue();
              });
}

// ==================== 槽查询方法实现 ====================

int QOverlay::slotCount() const {
    return Slots.size();
}

QList<QOverlay::OverlaySlot*> QOverlay::overlaySlots() const {
    return Slots;
}
